package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    WemediaFeign wemediaFeign;
    @Value("${file.oss.web-site}")
    private String webSite;

    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void autoScanByMediaNewsId(Integer wmNewsId) {
        //1. 根据文章id 远程调用 feign 查询文章
        if (wmNewsId == null) {
            log.error("自动审核文章失败  ,Id 为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        ResponseResult<WmNews> wmNewsResult = wemediaFeign.findById(wmNewsId);
        if (wmNewsResult.getCode().intValue() != 0) {
            log.error("自动审核文章失败  远程查询文章信息失败,原因:{}", wmNewsResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        WmNews wmNews = wmNewsResult.getData();
        if (wmNews == null) {
            log.error("自动审核文章不存在  为查询自媒体文章信息失败,原因:{}", wmNewsId);
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 2. 判断文章状态是否为 4 或8 (审核通过) 并 判断发布时间是否小于等于当前时间
        Short status = wmNews.getStatus();
        if (status == WmNews.Status.ADMIN_SUCCESS.getCode() || status == WmNews.Status.SUCCESS.getCode()
                && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            //保存数据
            publishArticle(wmNews);
            return;
        }

        //3. 判断文章状态是否为1(待审核) 进入审核
        if (status == WmNews.Status.SUBMIT.getCode()) {
            //抽取出文章中 所有的文本内容 和 所有的图片url 集合
            // content内容 imagesList 图片
            Map<String, Object> contentAndImagesResult = handleTextAndImages(wmNews);
            //3.1 敏感词审核 失败 修改文章状态(2)
            boolean isSensitiveScan = handleSensitive((String) contentAndImagesResult.get("content"), wmNews);
            if (!isSensitiveScan) return;

            // 3.2 阿里云的文本审核 失败 状态2 不确定 状态3
            boolean isTextScan = handleTextScan((String) contentAndImagesResult.get("content"), wmNews);
            if (!isTextScan) return;
            //3.3 阿里云的图片审核 失败 状态2 不确定 状态3
            boolean isImageScan = handleImagesScan((List<String>) contentAndImagesResult.get("images"), wmNews);
            if (!isImageScan) return;

            //4.判断文章发布时间是否大于当前时间  状态8
            if (wmNews.getPublishTime().after(new Date())) {
                updateWmNews(wmNews, WmNews.Status.SUCCESS.getCode(), "审核成功");
                return;
            }
            //5. 发布文章
            publishArticle(wmNews);
        }

    }

    @Autowired
    GreenImageScan greenImageScan;
    //图片审核-阿里云
    private boolean handleImagesScan(List<String> images, WmNews wmNews) {
        boolean flag = true;
        if (images == null || images.size() == 0) {
            return false;
        }
        images = images.stream()
                .distinct()
                .collect(Collectors.toList());
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "block":
                    flag = false;
                    updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "文章图片有违规");
                    break;
                case "review":
                    flag = false;
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "文章图片有不确定元素");
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核出现异常,原因{}", e.getMessage());
            updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "文章阿里云内容审核失败,转入人工审核");
            flag = false;
        }
        return flag;

    }

    @Autowired
    GreenTextScan greenTextScan;

    //审核文内容-阿里云
    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {

                case "block":
                    flag = false;
                    updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "文本中有敏感词汇");
                    break;
                case "review":
                    flag = false;
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "文本内容需要人工审核");
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            log.error("阿里云文本审核出现异常,原因{}", e.getMessage());
            updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "文章阿里云内容审核失败,转入人工审核");
        }
        return flag;
    }

    @Autowired
    AdSensitiveMapper adSensitiveMapper;

    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        //1.查询数据库中的敏感词
        List<String> allSensitive = adSensitiveMapper.findAllSensitive();

        //2.将敏感词集合转发DFA 数据模型
        SensitiveWordUtil.initMap(allSensitive);
        //3.检测敏感词
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if (resultMap != null && resultMap.size() > 0) {
            flag = false;
            updateWmNews(wmNews, (short) 2, "文章中包含了敏感词:" + resultMap);
        }
        return flag;
    }

    //修改文章状态
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if (responseResult.getCode().intValue() != 0) {
            log.error("远程调用 updateWmNews 方法失败  参数:{}", wmNews);
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR, responseResult.getErrorMessage());
        }
    }

    // 抽取文本内容 和图片路径
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //  获取文章内容并转换对象
        String content1 = wmNews.getContent();
        if (StringUtils.isBlank(content1)) {
            log.error("自动审核文章失败,文章内容为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "文章内容为空");
        }
        List<Map> maps = JSON.parseArray(content1, Map.class);

        //1.抽取文章中所有文本
        String content = maps.stream()
                .filter(map -> "text".equals(map.get("type")))
                .map(map -> ((String) map.get("value")))
                .collect(Collectors.joining("_hmtt_"));
        // 文章标题 参与审核
        content = wmNews.getTitle() + "_hmtt_" + content;
        //2.抽取文章中 所有图片
        List<String> imageList = maps.stream()
                .filter(map -> "image".equals(map.get("type")))
                .map(map -> map.get("value").toString())
                .collect(Collectors.toList());
        // 处理封面前缀 1.jpg 2.jpg
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            // 按照逗号 切割封面字符串 得到数组 基于数组得到stream
            // 将每一条数据都 拼接一个前缀 收集 成集合
            List<String> urls = Arrays.stream(wmNews.getImages().split(","))
                    .map(url -> webSite + url)
                    .collect(Collectors.toList());
            imageList.addAll(urls);
        }
        //3.去重
        imageList = imageList.stream().distinct().collect(Collectors.toList());
        Map result = new HashMap<>();
        result.put("content", content);
        result.put("images", imageList);
        return result;
    }
    @Autowired
    ArticleFeign articleFeign;
    //发布文章的方法
    private void publishArticle(WmNews wmNews) {
        //1. 远程调用saveArticle 保存3张表的信息
        ResponseResult responseResult = saveArticle(wmNews);
            if (responseResult.getCode().intValue()!=0) {
            log.error("远程保存apArticle信息失败： {}",responseResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"远程保存apArticle信息失败");
        }
        //2. 修改自媒体文章状态  9
        wmNews.setArticleId((Long)responseResult.getData());
        updateWmNews(wmNews,(short) 9 ,"发布成功");
        //TODO 3. 通知ES索引库 添加对应文章
    }
    @Autowired
    AdChannelMapper adChannelMapper;
    /**
     * 远程调用feign保存三张表信息
     * @param wmNews
     * @return
     */
    private ResponseResult saveArticle(WmNews wmNews) {
        //1. 封装dto参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        // 如果之前没发布过  id为null 发布过  为之前关联的articleId
        //拷贝属性
        articleDto.setId(wmNews.getArticleId());
        articleDto.setLayout(wmNews.getType()); // 布局
        // 0 普通文章
        articleDto.setFlag((byte) 0);

        // 自媒体用户id 用于在article服务中查询相关作者信息
        articleDto.setWmUserId(wmNews.getUserId());

        if(wmNews.getChannelId()!=null){
            // 设置频道信息
            AdChannel channel = adChannelMapper.selectById(wmNews.getChannelId());
            articleDto.setChannelName(channel.getName());
        }

        // 远程调用 article微服务保存3张表方法
        ResponseResult responseResult = articleFeign.saveArticle(articleDto);

        return responseResult;
    }

}